﻿using DLL.MSDM.Entity.Param;
using DLL.NET.ComPort;
using DLL.NET.DJ.OneDJ;

using DLL.NET70.Infrastructure.Prism;
using DLL.NET70.Infrastructure.Prism.MVVM;
using DLL.Standard.Infrastructure.Log;

using Module.NetCore.Commonly.Views;
using Prism.Commands;
using Prism.Events;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Regions;

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO.Ports;
using System.Linq;
using System.Threading;

namespace Module.ExternalDevice.DuoJi.ViewModels
{
    public class PUC_OneDjTestViewModel : CMVVMBase, IRegionMemberLifetime
    {
        public bool KeepAlive
        {
            get
            {
                //return false;//这个的作用是，只要离开当前切面，就注销掉当前页面
                return false;//这个的作用是，只要离开当前切面，就注销掉当前页面
            }
        }

        private IRegionManager _regionManager;
        private IContainerExtension _container;
        private IDJCtrlOne _djCtrl;

        private SerialSetting settings = new SerialSetting();

        public PUC_OneDjTestViewModel(IRegionManager regionManager,
            IEventAggregator ea,
            IApplicationCommands applicationCommands,
            IContainerExtension container,
            IDJCtrlOne dJCtrlOne

            ) : base(regionManager, ea, applicationCommands)
        {
            _regionManager = regionManager;
            _container = container;
            _djCtrl = dJCtrlOne;

            Title = "单个舵机";
            try
            {
                cb_ComNameSelectedChangedCommand = new DelegateCommand(CB_ComNameSelectedChanged);
                cb_BaudRateSelectedChangedCommand = new DelegateCommand(cb_BaudRateSelectedChanged);
            }
            catch (Exception e)
            {
                LogHelper.Warn("PUC_OpenComViewModel:" + e.Message);
            }

            #region duoji

            MoveToPos1Command = new DelegateCommand(MoveToPos1).ObservesCanExecute(() => ComIsEnabled);
            MoveToPos2Command = new DelegateCommand(MoveToPos2).ObservesCanExecute(() => ComIsEnabled);
            ReadPosCommand = new DelegateCommand(ReadPos).ObservesCanExecute(() => ComIsEnabled);

            for (byte i = 0; i < 10; i++)
            {
                _djID.Add(i);
            }

            #endregion duoji
        }

        #region windows load

        private CDJ_Type djType = new CDJ_Type();

        public override void Loaded()
        {
            #region 读取COM口参数文件

            //读取 舵机类型文件，根据同的舵机，读取不同的参数
            CDJ_Type_WR type_WR = new CDJ_Type_WR();
            bool ret = type_WR.ReadParam();
            if (true == ret)
            {
                djType = type_WR.DjParam;
            }
            else
            {
                djType.DjType = 0;
            }
            if (djType.DjType == 0)
            {
                Pos1 = 1500;
                Pos2 = 2000;
            }
            else if (djType.DjType == 1)
            {
                Pos1 = 200;
                Pos2 = 400;
            }
            else if (djType.DjType == 2)
            {
                Pos1 = 50;
                Pos2 = -700;
            }
            else
            {
                Pos1 = 1500;
                Pos2 = 2000;
            }

            #endregion 读取COM口参数文件

            InitializeCom();
            //_djCtrl.ReadComParam();
            //ComName = settings.cSerialEntity.PortName;
            //BaudRate = settings.cSerialEntity.BaudRate;
            base.Loaded();
        }

        public override void UnLoaded()
        {
            _djCtrl.SerialPortManager.CloseCom();
            base.UnLoaded();
        }

        #endregion windows load

        #region Com name   Process

        //CComBase comBase ;
        private void InitializeCom()
        {
            try
            {
                #region com command

                //串口名称
                settings = _djCtrl.SerialPortManager.CurrentSerialSettings;
                ComNames = settings.PortNameCollection;
                BaudRates = settings.BaudRateCollection;

                #endregion com command
            }
            catch (Exception e)
            {
                LogHelper.Warn("PUC_OpenComViewModel:" + e.Message);
            }
        }

        private string _comName = "COM1";

        public string ComName
        {
            get { return _comName; }
            set { SetProperty(ref _comName, value); }
        }

        //ComNames
        private string[] _comNames;

        public string[] ComNames
        {
            get { return _comNames; }
            set { SetProperty(ref _comNames, value); }
        }

        private object _cb_ComNameSelectItem;

        public object cb_ComNameSelectItem
        {
            get { return _cb_ComNameSelectItem; }
            set { SetProperty(ref _cb_ComNameSelectItem, value); }
        }

        public int _BaudRate = 9600;

        public int BaudRate
        {
            get { return _BaudRate; }
            set { SetProperty(ref _BaudRate, value); }
        }

        private BindingList<int> _baudRates = new BindingList<int>();

        public BindingList<int> BaudRates
        {
            get { return _baudRates; }
            set { SetProperty(ref _baudRates, value); }
        }

        private object _cb_BaudRateSelectItem;

        public object cb_BaudRateSelectItem
        {
            get { return _cb_BaudRateSelectItem; }
            set { SetProperty(ref _cb_BaudRateSelectItem, value); }
        }

        public DelegateCommand cb_ComNameSelectedChangedCommand { get; private set; }

        private void CB_ComNameSelectedChanged()
        {
            if (cb_ComNameSelectItem != null)
            {
                ComName = cb_ComNameSelectItem.ToString();
                settings.cSerialEntity.PortName = ComName;
            }
        }

        public DelegateCommand cb_BaudRateSelectedChangedCommand { get; private set; }

        private void cb_BaudRateSelectedChanged()
        {
            if (cb_BaudRateSelectItem != null)
            {
                BaudRate = Convert.ToInt32(cb_BaudRateSelectItem.ToString());
                settings.cSerialEntity.BaudRate = BaudRate;
            }
        }

        private string _connectedStateBrush = "Gray";

        public string ConnectedStateBrush
        {
            get { return _connectedStateBrush; }
            set { SetProperty(ref _connectedStateBrush, value); }
        }

        private bool _isEnabled = false;

        public bool ComIsEnabled
        {
            get { return _isEnabled; }
            set
            {
                SetProperty(ref _isEnabled, value);
            }
        }

        private bool _OpenComEnabled = true;

        public bool OpenComEnabled
        {
            get { return _OpenComEnabled; }
            set
            {
                SetProperty(ref _OpenComEnabled, value);
            }
        }

        public DelegateCommand OpenComCommand
        { get { return new DelegateCommand(OpenCom).ObservesCanExecute(() => OpenComEnabled); } }

        public DelegateCommand CloseComCommand
        { get { return new DelegateCommand(CloseCom).ObservesCanExecute(() => ComIsEnabled); } }

        private void OpenCom()
        {
            _djCtrl.SerialPortManager.CurrentSerialSettings = settings;
            bool ret = _djCtrl.OpenCom(ComName, Convert.ToInt32(BaudRate));
            if (false == ret)
            {
                LogMessage("串口打开失败！");
                return;
            }
            if (_djCtrl.SerialPortManager.IsOpen == true)
            {
                ConnectedStateBrush = "Green";
                ComIsEnabled = true;
                OpenComEnabled = false;
                ThreadStartEnabled = true;
                UpdateStartEnabled = true;
            }
            else
            {
                ConnectedStateBrush = "Gray";
                OpenComEnabled = true;
                ComIsEnabled = false;
                ThreadStartEnabled = false;
                UpdateStartEnabled = false;
            }
            LogMessage("串口打开成功！");
        }

        private void CloseCom()
        {
            try
            {
                if (_djCtrl.SerialPortManager.IsOpen == true)
                {
                    _djCtrl.SerialPortManager.CloseCom();
                }
                if (_djCtrl.SerialPortManager.IsOpen == true)
                {
                    ConnectedStateBrush = "Green";
                    ComIsEnabled = true;
                }
                else
                {
                    ConnectedStateBrush = "Gray";
                    ComIsEnabled = false;
                }
            }
            catch (Exception e)
            {
                LogMessage("关闭串口出现异常：" + e.Message);
            }
            OpenComEnabled = true;
            ComIsEnabled = false;
            ThreadStartEnabled = false;
            UpdateStartEnabled = false;
        }

        //public DelegateCommand SaveComCommand
        //{
        //    get { return new DelegateCommand(SaveCom); }//.ObservesCanExecute(() => IsEnabled);
        //}

        //private void SaveCom()
        //{
        //    if ((ComName.Length > 0) && (BaudRate > 0))
        //    {
        //        settings.cSerialEntity.BaudRate = BaudRate;
        //        settings.cSerialEntity.PortName = ComName;
        //        _djCtrl.SerialPortManager.CurrentSerialSettings = settings;
        //        _djCtrl.SaveComParam();
        //        LogMessage("串口参数保存成功！");
        //    }
        //    else
        //    {
        //        LogMessage("串口参数保存失败！");
        //    }
        //}

        #endregion Com name   Process

        #region 舵机操作

        private ObservableCollection<byte> _djID = new ObservableCollection<byte>();

        public ObservableCollection<byte> DjID
        {
            get { return _djID; }
            set { SetProperty(ref _djID, value); }
        }

        private byte _SelectedDjID = 0;

        public byte SelectedDjID
        {
            get { return _SelectedDjID; }
            set { SetProperty(ref _SelectedDjID, value); }
        }

        private int _Interval = 2000;

        public int Interval
        {
            get { return _Interval; }
            set { SetProperty(ref _Interval, value); }
        }

        private ushort _RunSpeed = 1000;

        public ushort RunSpeed
        {
            get { return _RunSpeed; }
            set { SetProperty(ref _RunSpeed, value); }
        }

        #endregion 舵机操作

        #region 舵机运动

        public DelegateCommand MoveToPos1Command { get; set; }
        public DelegateCommand MoveToPos2Command { get; set; }
        public DelegateCommand ReadPosCommand { get; set; }

        private void MoveToPos1()
        {
            if (SelectedDjID >= 0)
            {
                byte id = Convert.ToByte(SelectedDjID);
                _djCtrl.MoveToDstAngle(id, Pos1, RunSpeed);
            }
        }

        private void MoveToPos2()
        {
            if (SelectedDjID >= 0)
            {
                byte id = Convert.ToByte(SelectedDjID);
                _djCtrl.MoveToDstAngle(id, Pos2, RunSpeed);
            }
        }

        private void ReadPos()
        {
            if (SelectedDjID >= 0)
            {
                byte id = Convert.ToByte(SelectedDjID);
                int pos = 0;
                pos = _djCtrl.ReadPos(id);
                ReadPos1 = pos;
            }
        }

        #endregion 舵机运动

        #region loop run property

        private bool _ThreadStartEnabled = false;

        public bool ThreadStartEnabled
        {
            get { return (_ThreadStartEnabled); }
            set
            {
                SetProperty(ref _ThreadStartEnabled, value);
            }
        }

        private bool _ThreadStopEnabled = false;

        public bool ThreadStopEnabled
        {
            get { return (_ThreadStopEnabled); }
            set
            {
                SetProperty(ref _ThreadStopEnabled, value);
            }
        }

        private int _LoopIndex = 0;

        public int LoopIndex
        {
            get { return _LoopIndex; }
            set { SetProperty(ref _LoopIndex, value); }
        }

        private int _LoopCount = 10;

        public int LoopCount
        {
            get { return _LoopCount; }
            set { SetProperty(ref _LoopCount, value); }
        }

        private short _Pos1 = 1500;

        public short Pos1
        {
            get { return _Pos1; }
            set { SetProperty(ref _Pos1, value); }
        }

        private short _Pos2 = 2000;

        public short Pos2
        {
            get { return _Pos2; }
            set { SetProperty(ref _Pos2, value); }
        }

        private int _ReadPos1 = 0;

        public int ReadPos1
        {
            get { return _ReadPos1; }
            set { SetProperty(ref _ReadPos1, value); }
        }

        private int _ReadPos2 = 0;

        public int ReadPos2
        {
            get { return _ReadPos2; }
            set { SetProperty(ref _ReadPos2, value); }
        }

        #endregion loop run property

        #region loop run function

        public DelegateCommand LoopRunCommand
        {
            get { return new DelegateCommand(LoopRun).ObservesCanExecute(() => ThreadStartEnabled); }
        }

        private void LoopRun()
        {
            if (true == StopLoop)
            {
                StopLoop = false;
                ThreadStartEnabled = false;
                ThreadStopEnabled = true;
                //开启线程
                Thread thread = new Thread(new ThreadStart(ThreadLoopRun));//创建线程
                thread.Start();
                //开启定时器
                //t.Enabled = true;
                //t.Start();
            }
        }

        private void ThreadLoopRun()
        {
            LoopIndex = 0;
            byte DJID = SelectedDjID;
            for (int i = 0; i < LoopCount; i++)
            {
                if (true == StopLoop)
                {
                    _djCtrl.MoveToDstAngle(DJID, Pos1, RunSpeed);
                    return;
                }
                LoopIndex = i + 1;
                //first step move to org angle
                _djCtrl.MoveToDstAngle(DJID, Pos1, RunSpeed);
                ReadPos1 = _djCtrl.CurrentPos;

                Thread.Sleep(Interval * 2);
                _djCtrl.MoveToDstAngle(DJID, Pos2, RunSpeed);
                ReadPos2 = _djCtrl.CurrentPos;

                Thread.Sleep(Interval);
            }
            StopLoop = true;
            ThreadStartEnabled = true;
            ThreadStopEnabled = false;
            _djCtrl.MoveToDstAngle(DJID, Pos1, (ushort)Interval);
        }

        private void LogPos(byte DJID, int dstAngle, int ReAngle)
        {
            int sub = dstAngle - ReAngle;
            if (Math.Abs(sub) > 100)
            {
                LogHelper.Warn("舵机ID=" + DJID.ToString() + "目标角度=" + dstAngle.ToString() + ";读取到角度=" + ReAngle.ToString() + ";相差角度=" + sub.ToString());
            }
            else
            {
                LogHelper.Info("舵机ID=" + DJID.ToString() + "目标角度=" + dstAngle.ToString() + ";读取到角度=" + ReAngle.ToString());
            }
        }

        public DelegateCommand LoopStopCommand
        {
            get { return new DelegateCommand(LoopStop).ObservesCanExecute(() => ThreadStopEnabled); }
        }

        private bool StopLoop = true;

        private void LoopStop()
        {
            LoopIndex = 0;
            StopLoop = true;
            ThreadStartEnabled = true;
            ThreadStopEnabled = false;
        }

        #endregion loop run function

        #region 舵机状态属性变量

        private bool _UpdateStartEnabled = false;

        public bool UpdateStartEnabled
        {
            get { return (_UpdateStartEnabled); }
            set
            {
                SetProperty(ref _UpdateStartEnabled, value);
            }
        }

        private bool _UpdateStopEnabled = false;

        public bool UpdateStopEnabled
        {
            get { return (_UpdateStopEnabled); }
            set
            {
                SetProperty(ref _UpdateStopEnabled, value);
            }
        }

        private string _Voltage = "0";

        public string Voltage
        {
            get { return _Voltage; }
            set { SetProperty(ref _Voltage, value); }
        }

        private string _Current = "0";

        public string Current
        {
            get { return _Current; }
            set { SetProperty(ref _Current, value); }
        }

        private string _Power = "0";

        public string Power
        {
            get { return _Power; }
            set { SetProperty(ref _Power, value); }
        }

        private string _Temperature = "0";

        public string Temperature
        {
            get { return _Temperature; }
            set { SetProperty(ref _Temperature, value); }
        }

        private string _Status = "0";

        public string Status
        {
            get { return _Status; }
            set { SetProperty(ref _Status, value); }
        }

        public DelegateCommand UpdateDataStartCommand
        {
            get { return new DelegateCommand(UpdateDataStart).ObservesCanExecute(() => UpdateStartEnabled); }
        }

        private bool StopUpdate = true;

        private void UpdateDataStart()
        {
            //return;
            //开启线程
            StopUpdate = false;
            UpdateStopEnabled = true;
            UpdateStartEnabled = false;

            Thread thread = new Thread(new ThreadStart(ReadData));//创建线程
            thread.Start();
        }

        private void ReadData()
        {
            while (false == StopUpdate)
            {
                ReadOne();
            }
        }

        private void ReadOne()
        {
            Thread.Sleep(200);
            byte DJID = SelectedDjID;
            Voltage = _djCtrl.ReadVoltage(DJID).ToString();
            Current = _djCtrl.ReadCurrent(DJID).ToString();
            Power = _djCtrl.ReadPower(DJID).ToString();
            Temperature = _djCtrl.ReadTemperature(DJID).ToString();
            Status = _djCtrl.ReadStatus(DJID).ToString();
        }

        public DelegateCommand UpdateDataStopCommand
        {
            get { return new DelegateCommand(UpdateDataStop).ObservesCanExecute(() => UpdateStopEnabled); }
        }

        private void UpdateDataStop()
        {
            StopUpdate = true;
            UpdateStopEnabled = false;
            UpdateStartEnabled = true;
        }

        #endregion 舵机状态属性变量
    }
}